#:kivy 1.9.1

#<Widget>:
#This can be used to create boxes around each widget to clarify positioning issues. It is only for debug
#    canvas.after:
#        Line:
#            rectangle: self.x+1,self.y+1,self.width-1,self.height-1
#            dash_offset: 5
#            dash_length: 3

<ButtonTemplate>:
    GridLayout:
        cols: 1
        size: root.size
        pos: root.pos
        Button:
            border: (2, 2, 2, 2)
            background_normal: root.btnBackground      # The background when the button is not pressed
            background_down:   root.btnBackgroundDown  # The background when the button is pressed
            on_press: root.internal_on_press()
            on_release: root.internal_on_release()
            Label:
                text: root.textColor + root.text + '[/color]'
                markup: True
                pos: (root.pos[0] + (root.width - self.width)/2, root.pos[1] + (root.height-self.height)/2)

<ScreenControls>:
    actionsBtn:actionsBtn
    settingsBtn:settingsBtn
    backgroundBtn:backgroundBtn

    BoxLayout:
        orientation: 'horizontal'
        pos: (0, root.height - dp(60))
        size_hint: (.4,None)
        height: dp(60)

        ButtonTemplate:
            text: "Actions"
            funcToCallOnRelease: root.show_actions
            id: actionsBtn
        ButtonTemplate:
            text: "Settings"
            funcToCallOnRelease: root.openSettings
            id: settingsBtn
        ButtonTemplate:
            text: "Background"
            funcToCallOnRelease: root.open_background
            id: backgroundBtn

<GcodeCanvas>:
    scatterObject:scatterObject
    scatterInstance:scatterInstance
    positionIndicator:positionIndicator
    targetIndicator:targetIndicator

    ScatterPlane:
        do_rotation: False
        id: scatterInstance
        Label:
            id: scatterObject
            text: ""
        PositionIndicator:
            id: positionIndicator
        PositionIndicator:
            id: targetIndicator
        MenuSpawner:
            timeout: 1
            menu_args:
                dict(
                creation_direction=1,
                radius=10,
                creation_timeout=.2,
                choices=[
                dict(text='[color=3333ff]Move Here[/color]', markup = True, index=1),
                dict(text='Position Text Placeholder'      , markup = True, index=2),
                dict(text='[color=3333ff]Set Home[/color]' , markup = True, index=3),
                dict(text='[color=3333ff]Mark Here[/color]', markup = True, index=4)])

<FrontPage>:
    textconsole:textconsole
    moveDistInput:moveDistInput
    moveSpeedInput:moveSpeedInput
    gcodecanvas:gcodecanvas
    screenControls:screenControls
    holdBtn:holdBtn
    macro1Btn:macro1Btn
    macro2Btn:macro2Btn

    upLeftArrow:upLeftArrow
    upArrow:upArrow
    upRightArrow:upRightArrow
    leftArrow:leftArrow
    homeBtn:homeBtn
    rightArrow:rightArrow
    downLeftArrow:downLeftArrow
    downArrow:downArrow
    downRightArrow:downRightArrow

    zAxisBtn:zAxisBtn
    unitsBtn:unitsBtn
    defHomeBtn:defHomeBtn
    zLeft:zLeft
    zRight:zRight
    oneLeft:oneLeft
    oneRight:oneRight

    run:run
    stopBtn:stopBtn

    goTo:goTo


    GcodeCanvas:
        id: gcodecanvas
    BoxLayout:
        orientation: 'vertical'
        pos: root.width - dp(300), dp(0)
        GridLayout:
            cols: 4
            size_hint: None, None
            width:dp(300)
            height: dp(60*4)
            #disabled: not app.data.connectionStatus
            ButtonTemplate:
                id: upLeftArrow
                funcToCallOnPress: root.upLeft
            ButtonTemplate:
                id: upArrow
                funcToCallOnPress: root.up
            ButtonTemplate:
                id: upRightArrow
                funcToCallOnPress: root.upRight
            ButtonTemplate:
                id: macro1Btn
                text: "Macro 1"
                funcToCallOnPress: lambda:root.macro(1)
            ButtonTemplate:
                id: leftArrow
                funcToCallOnPress: root.left
            ButtonTemplate:
                id: homeBtn
                funcToCallOnPress: root.home
            ButtonTemplate:
                id: rightArrow
                funcToCallOnPress: root.right
            ButtonTemplate:
                id: macro2Btn
                text: "Macro 2"
                funcToCallOnPress: lambda:root.macro(2)
            ButtonTemplate:
                id: downLeftArrow
                funcToCallOnPress: root.downLeft
            ButtonTemplate:
                id: downArrow
                funcToCallOnPress: root.down
            ButtonTemplate:
                id: downRightArrow
                funcToCallOnPress: root.downRight
            ButtonTemplate:
                id: zAxisBtn
                disabled: app.data.uploadFlag == 1 #zAxisPopup can change units... don't let it be popped during a move!
                text: 'Z-Axis'
                funcToCallOnPress: root.zAxisPopup
            Label:
                id: moveSpeedInput
                color: .476, .476, .476,1
                text: 'Dist To \nMove:'
                multiline: False
            ButtonTemplate:
                id: moveDistInput
                text: '100'
                multiline: False
                funcToCallOnPress: lambda:root.textInputPopup(self)
            ButtonTemplate:
                text: root.units
                funcToCallOnPress: root.switchUnits
                id: unitsBtn
            ButtonTemplate:
                text: 'Define\nHome'
                funcToCallOnPress: root.moveOrigin
                id: defHomeBtn

        GridLayout:
            cols: 3
            size_hint: None, None
            width: dp(300)
            height: dp(60)
            #disabled: not app.data.connectionStatus
            ButtonTemplate:
                id: run
                funcToCallOnPress: root.startRun
            ButtonTemplate:
                id: holdBtn
                secretText: "HOLD"
                funcToCallOnPress: root.pause
            ButtonTemplate:
                id: stopBtn
                funcToCallOnPress: root.stopRun
        GridLayout:
            cols: 5
            size_hint: None, None
            width: dp(300)
            height: dp(30)
            #disabled: not app.data.connectionStatus
            ButtonTemplate:
                text: "<Z"
                funcToCallOnPress: lambda:root.moveGcodeZ(-1)
                id: zLeft
            ButtonTemplate:
                text: "<1"
                funcToCallOnPress: lambda:root.moveGcodeIndex(-1)
                id: oneLeft
            ButtonTemplate:
                id: goTo
                #text: 'GoTo'
                funcToCallOnPress: root.gotoLinePopup
            ButtonTemplate:
                text: "1>"
                funcToCallOnPress: lambda:root.moveGcodeIndex(1)
                id: oneRight
            ButtonTemplate:
                text: "Z>"
                funcToCallOnPress: lambda:root.moveGcodeZ(1)
                id: zRight
        BoxLayout:
            orentation: 'horizontal'
            size_hint: None, None
            width: dp(300)
            height: dp(70)
            #disabled: not app.data.connectionStatus
            GridLayout:
                cols: 2
                Label:
                    text: '                   X :'
                    color: .476, .476, .476,1
                Label:
                    text: root.xReadoutPos
                    color: .476, .476, .476,1
                Label:
                    text: '                   Y : '
                    color: .476, .476, .476,1
                Label:
                    text: root.yReadoutPos
                    color: .476, .476, .476,1
                Label:
                    text: '                   Z : '
                    color: .476, .476, .476,1
                Label:
                    text: root.zReadoutPos
                    color: .476, .476, .476,1
                Label:
                    text: '                 Vel : '
                    color: .476, .476, .476,1
                Label:
                    text: root.ReadoutVel
                    color: .476, .476, .476,1
            GridLayout:
                cols: 1
                Label:
                    text: "Percent Complete/Line:"
                    font_size: '11sp'
                    color: .476, .476, .476,1
                Label:
                    text: root.percentComplete
                    color: .476, .476, .476,1
                Label:
                    text: root.gcodeLineNumber
                    color: .476, .476, .476,1
                Label:
                    text: root.gcodeVel
                    color: .476, .476, .476,1
        Label:
            text: root.connectionStatus
            size_hint: None, None
            width: dp(300)
            height: dp(30)
            disabled: False
            color: .476, .476, .476,1
        ScrollableLabel:
            id: textconsole
            size: dp(300), root.height - dp(430)
            text: root.consoleText
            size_hint: None, None

    ScreenControls:
        id: screenControls
        size_hint: (1, 1)

<ViewMenu>:
    cols:1
    size: root.size
    pos: root.pos
    Label:
        text: "View"
    Button:
        text: 'Open File'
        on_press: root.openFile()
        disabled: app.data.uploadFlag == 1
    Button:
        text: 'Update Gcode'
        on_release: root.reloadGcode()
        disabled: app.data.uploadFlag == 1
    Button:
        text: 'View Gcode'
        disabled: False
        on_press: root.show_gcode()
    Button:
        text: 'Clear Gcode'
        disabled: False
        on_press: root.clear_gcode()
    Button:
        text: 'Reset View'
        disabled: False
        on_press: app.frontpage.gcodecanvas.centerCanvas()
        on_release: root.resetView()

<RunMenu>:
    GridLayout:
        cols: 1
        size: root.size
        pos: root.pos
        Label:
            text: "Run"
        Button:
            text: 'Quit Ground Control'
            on_release: root.closeGC()
        Button:
            text: 'Return To Center'
            on_release: root.returnToCenter()
            #disabled: not app.data.connectionStatus
        Button:
            text: 'Zero Z'
            disabled: True
        Button:
            text: 'Auto Zero Z'
            disabled: True

<ScrollableLabel>:
    Label:
        size_hint_y: None
        height: self.texture_size[1]
        text_size: self.width, None
        text: root.text
        color: .476, .476, .476,1

<ConnectMenu>:
    GridLayout:
        cols: 1
        size: root.size
        pos: root.pos
        Label:
            text: "Connect"
        Button:
            text: 'Connect'
            on_press: root.connect()
        Spinner:
            id: ports
            text: "Ports"
            values: root.COMports
            on_text: root.setPort(ports.text)
        Button:
            text: 'Update List'
            on_press: root.updatePorts()

<Diagnostics>:
    GridLayout:
        rows: 2
        size: root.size
        pos: root.pos
        Label:
            text: "Diagnostic features"
        GridLayout:
            cols: 3
            #disabled: not app.data.connectionStatus
            Button:
                text: 'Test Motors/Encoders'
                on_press: root.testMotors()
            Button:
                text: 'Calibrate'
                on_release: root.calibrateMachine()
            Button:
                text: 'Set Chain Length - Automatic'
                on_release: root.calibrateChainLengths()
            Button:
                text: 'Manual Calibration'
                on_release: root.manualCalibration()
            Button:
                text: 'About'
                on_release: root.about()
            Spinner:
                id: advancedOptions
                text: "Advanced"
                values: ["Set Chain Length - Manual", "Wipe EEPROM", "Simulation", "Load Calibration Benchmark Test", "Run Triangular Test Cut Pattern", "Reset settings to defaults", "Compute chain calibration factors"]
                on_text: root.advancedOptionsFunctions(advancedOptions.text)

<OtherFeatures>:
    connectmenu:connectmenu
    viewmenu:viewmenu
    diagnostics:diagnostics
    runmenu:runmenu

    BoxLayout:
        orientation: 'vertical'
        BoxLayout:
            orientation: 'horizontal'
            padding:2
            spacing:0

            ViewMenu:
                id: viewmenu
            RunMenu:
                id: runmenu
            ConnectMenu:
                id: connectmenu
        BoxLayout:
            orientation: 'vertical'
            padding:2
            spacing:0

            Diagnostics:
                id: diagnostics
            Button:
                text: "Close"
                size_hint_y: .15
                on_release: root.close()

<SoftwareSettings>:

<PositionIndicator>:
    size: 50, 50
    canvas:
        Color:
            rgb: root.color
        Line:
            circle:
                (self.center_x-self.width/2, self.center_y-self.height/2, min(self.width, self.height)/ 2)
        Line:
            circle:
                (self.center_x-self.width/2, self.center_y-self.height/2, self.positionErrorRadius)
        Line:
            circle:
                (self.center_x-self.width/2, self.center_y-self.height/2, .5)
        Line:
            points: (self.x-self.width/2, self.y-self.height/2, self.width/2+self.x, self.height/2+self.y)
        Line:
            points: (self.x-self.width/2, self.height/2+self.y, self.width/2+self.x, self.y-self.height/2)

<NotificationPopup>:
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"

        ScrollableLabel:
            text: root.text

        BoxLayout:
            size_hint_y: None
            height: dp(60)
            Button:
                text: "Continue"
                on_release: root.continueOn()

<ScrollableTextPopup>:
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"

        ScrollableLabel:
            text: root.text

        BoxLayout:
            size_hint_y: None
            height: dp(60)
            Button:
                text: "Close"
                on_release: root.cancel()

<PageableTextPopup>:
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"

        ScrollableLabel:
            text: root.text

        BoxLayout:
            size_hint_y: None
            height: dp(30)
            Button:
                text: "Prev"
                on_release: root.prev()
            Button:
                text: "Next"
                on_release: root.next()
            Button:
                text: "Close"
                on_release: root.cancel()

<SaveDialog>:
    text_input: text_input
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"
        FileChooserListView:
            id: filechooser
            on_selection: text_input.text = self.selection and self.selection[0] or ''

        TextInput:
            id: text_input
            size_hint_y: None
            height: dp(30)
            multiline: False

        BoxLayout:
            size_hint_y: None
            height: dp(30)
            Button:
                text: "Cancel"
                on_release: root.cancel()

            Button:
                text: "Save"
                on_release: root.save(filechooser.path, text_input.text)

<TouchNumberInput>:
    textInput:textInput
    unitsBtn:unitsBtn
    cols: 1
    size: root.size
    pos: root.pos
    GridLayout:
        cols: 2
        size_hint_y:.25
        TextInput:
            size_hint_x:.8
            font_size: self.height - 5
            id:textInput
            disabled: True
        Button:
            size_hint_x: .2
            text: 'MM'
            id: unitsBtn
            on_release: root.switchUnits()
    GridLayout:
        cols: 3
        Button:
            text: "1"
            on_release: root.addText("1")
        Button:
            text: "2"
            on_release: root.addText("2")
        Button:
            text: "3"
            on_release: root.addText("3")
        Button:
            text: "4"
            on_release: root.addText("4")
        Button:
            text: "5"
            on_release: root.addText("5")
        Button:
            text: "6"
            on_release: root.addText("6")
        Button:
            text: "7"
            on_release: root.addText("7")
        Button:
            text: "8"
            on_release: root.addText("8")
        Button:
            text: "9"
            on_release: root.addText("9")
        Button:
            text: "."
            on_release: root.addText(".")
        Button:
            text: "0"
            on_release: root.addText("0")
        Button:
            text: "Done"
            on_release: root.done()

<ZAxisPopupContent>:
    distBtn:distBtn
    unitsBtn:unitsBtn
    cols: 1
    size: root.size
    pos: root.pos
    GridLayout:
        cols: 3
        GridLayout:
            size_hint_x: ".75sp"
            cols: 4
            rows: 4
            Label:
                text: ""
                size_hint_y: 0.2
            Label:
                size_hint_y: 0.2
            Label:
                text: "Relative"
                size_hint_y: 0.2
            Label:
                text: "Absolute"
                size_hint_y: 0.2
            Button:
                text: "%.3f"%app.data.zStepSizeVal
                id: distBtn
                on_release: root.setDist()
            Button:
                text: "MM"
                on_release: root.units()
                id: unitsBtn
            Button:
                text: "Raise"
                on_release: root.zOut()
            GridLayout:
                cols:1
                rows:2
                Button:
                    text: "Plunge to\n-"+root.distBtn.text
                    halign: "center"
                    on_release: root.goThere()
                Button:
                    text: "Save and\nRaise to\nTraverse"
                    halign: "center"
                    on_release: root.zUp()
            Button:
                text: "Done"
                on_release: root.close()
            GridLayout:
                cols: 1
                rows: 2
                Button:
                    text: "Define Zero"
                    on_release: root.zero()
                Button:
                    size_hint_y: 0.2
                    text: "Touch Zero"
                    on_release: root.touchZero()
                    disabled: False
            Button:
                text: "Lower"
                on_release: root.zIn()
            GridLayout:
                cols:1
                rows:2
                Button:
                    text: "Go to Zero"
                    on_release: root.zToZero()
                Button:
                    text: root.zCutLabel
                    halign: "center"
                    disabled: root.zPopDisable
                    on_release: root.zToCut()
            Label:
                text: ""
                size_hint_y: 0.2
        GridLayout:
            size_hint_x: ".25sp"
            cols: 1
            rows: 1
            Button:
                text: "Stop!"
                # font_size: '48sp'
                # color: [1,0,0,1]
                on_release: root.stopZMove()

#calibration widgets

<CalibrationTemplate>:
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "Text about what to do in this step"
            size_hint_x: leftCol
        GridLayout:
            cols: 2
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Set Z Height.jpg"
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: "Thing one"
        Button:
            text: 'Thing two'
        Label:

<CalibrationFrameWidget>:
    cFrameWidgetSpace:cFrameWidgetSpace
    cols: 1
    size: root.size
    pos:  root.pos
    GridLayout:
        rows: 2
        width: root.width
        height: root.height
        id: cFrameWidgetSpace
        GridLayout:
            cols: 3
            size_hint_y: .1
            Button:
                text: "Back"
                on_release: root.back()
            Button:
                text: "Skip"
                on_release: root.loadNextStep()
            Button:
                text: "Quit"
                on_release: root.on_Exit()

<SetChainLengthsFrameWidget>:
    cFrameWidgetSpace:cFrameWidgetSpace
    cols: 1
    size: root.size
    pos:  root.pos
    GridLayout:
        rows: 2
        width: root.width
        height: root.height
        id: cFrameWidgetSpace
        GridLayout:
            cols: 3
            size_hint_y: .1
            Button:
                text: "Back"
                on_release: root.back()
            Button:
                text: "Skip"
                on_release: root.loadNextStep()
            Button:
                text: "Quit"
                on_release: root.on_Exit()

<Intro>:
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: 'This walk-through will guide you through the process of calibrating your Maslow Machine. \n\nYou can move forward and backwards through the walk-through at any time using the Back and Skip buttons\n\nYou can also skip this process entirely and enter your machine dimensions in the Settings window\n\nYour feedback on how to improve this process is more than welcome\n\nClick Begin to start. '
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Label:
            text: 'The controls you will need for each step will be on here on the right'
            text_size: self.size
        Button:
            text: "Begin"
            on_release: root.finished()
        Label:

<ChooseKinematicsType>:
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "Now we're going to select the way the chains attach to the sled. There are currently two options. \n\nThe \"Quadrilateral\" system attaches the chains to the two stationary metal L brackets as shown in the left picture.\nThis is currently the default option. \n\nThe \"Triangular\" system attaches the chains to a system of either linkages or bearings which let the ends of the chains\nrotate around the router bit as shown in the picture on the right.\n\n Please choose an option on the right."
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
        GridLayout:
            cols: 2
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Quadrilateral Kinematics.jpg"
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Triangular Kinematics.jpg"
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: 'Quadrilateral'
            on_release: root.setKinematicsTypeQuad()
        Button:
            text: 'Triangular'
            on_release: root.setKinematicsTypeTri()
        Label:

<ChooseChainOverSprocketDirection>:
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "Now we're going to select the direction in which the chains pass over the sprocket.\n\nDo your chains come from the top of the sprocket and connect to the sled as shown in the picture on the left\nor come from the bottom of the sprocket to connect to the machine as shown in the picture on the right?"
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
        GridLayout:
            cols: 2
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Chain off top.jpg"
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Chain off bottom.jpg"
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: 'Top'
            on_release: root.setChainToTop()
        Button:
            text: 'Bottom'
            on_release: root.setChainToBottom()
        Label:

<ComputeCalibrationSteps>
    cols: 1
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "The correct calibration procedure for your machine is being generated...please wait"
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1

<RemoveChains>:
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: 'Now we need to remove the chains from the machine so that we can put them back on\nin the correct direction for your bottom feeding configuration.\n\nRemove the chain from the sprocket, then press Next'
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: "Next"
            on_release: root.loadNextStep()
        Label:

<ReviewMeasurements>:
    cols: 2
    width: root.width
    height: root.height
    measurementsReadout:measurementsReadout
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: ""
            size_hint_x: leftCol
            id: measurementsReadout
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: "Looks Good!"
            on_release: root.loadNextStep()
        Label:

<TriangularCalibration>:
    cutBtnT:cutBtnT
    horzMeasureT1:horzMeasureT1
    horzMeasureT2:horzMeasureT2
    vertMeasureT1:vertMeasureT1
    bitDiameterT:bitDiameterT
    enterValuesT:enterValuesT
    unitsBtnT:unitsBtnT

    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "To refine these measurements we're going to cut a test shape. The test shape consists of five cuts.\n\nCuts 1 and 2 will be short vertical cuts in the upper left and right corners of the work area.\nCuts 3 and 4 will be short vertical cuts in the lower left and right corners of the work area.\nCut 5 will be a short horizontal cut attached to cut 2.\n\nBased on the distances between these cuts we can dial in the machine settings.\n\nFor the first measurement, measure from the left edge of cut 1 to the left edge of cut 2.\n\nFor the second measurement, measure from the left edge of cut 3 to the left edge of cut 4.\n\nFor the third measurement, measure from the top edge of the work area to the top edge of cut 5.\n\nEnter the diameter of the bit used to make the cuts (1/4\" = 6.35 mm).\n\nThe more accurate your measurements, the more accurate your machine will be.\n\nPress Cut Test Pattern to begin."
            text_size: self.size
            valign: 'middle'
        GridLayout:
            cols: 2
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Test Shape Preview Triangular.jpg"
                size_hint_x: 0.5
            Label:
                text: root.triangularCalText
                size_hint_x: 0.5
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Label:
            text: "Measurement\nBetween Cuts 1 and 2:"
            halign: "center"
        TextInput:
            id: horzMeasureT1
            disabled: True
        Label:
            text: "Measurement\nBetween Cuts 3 and 4:"
            halign: "center"
        TextInput:
            id: horzMeasureT2
            disabled: True
        Label:
            text: "Measurement\nWork Area Top to Cut 5:"
            halign: "center"
        TextInput:
            id: vertMeasureT1
            disabled: True
        Label:
            text: "Bit Diameter:"
            halign: "center"
        TextInput:
            id: bitDiameterT
            disabled: False
        Button:
            text: "Units: mm"
            on_release: root.switchUnitsT()
            id: unitsBtnT
            disabled: False
        Button:
            text: "Enter Values"
            halign: "center"
            on_release: root.enterTestPaternValuesTriangular()
            id: enterValuesT
            disabled: True
        Button:
            text: "Cut Test\nPattern"
            halign: "center"
            id: cutBtnT
            on_release: root.cutTestPaternTriangular()
        Button:
            text: "Stop\nCut"
            halign: "center"
            on_release: root.stopCut()
            background_color: (1,.2,.2,1)
        Label:

<ComputeChainCorrectionFactors>:
    selfText:selfText

    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "placeholder text"
            id: selfText
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: "Looks\nGood"
            halign: "center"
            on_release: root.loadNextStep()
            id: enterValues
        Label:

<EnterDistanceBetweenMotors>:
    motorsDist:motorsDist
    unitsBtnT:unitsBtn

    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "Enter the distance from the outside edge of one motor to the outside edge of the other motor.\n\nWe measure to the edge because it is easier.\n\n{picture coming soon}"
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Label:
            text: "Distance Between Motors:"
            halign: "center"
        TextInput:
            id: motorsDist
        Button:
            text: "Units: mm"
            on_release: root.switchUnits()
            id: unitsBtn
        Button:
            text: "Enter Values"
            halign: "center"
            on_release: root.enterValues()
            id: enterValues
        Label:

<WipeOldCorrectionValues>:
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "We need to wipe any existing values for the chain correction values before computing new ones.\n\nThis step will set the values to 0"
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: "Wipe Current\nValues"
            halign: "center"
            on_release: root.wipeOldSettings()
            id: enterValues
        Label:

<ManualCalibration>:
    motorsDist:motorsDist
    rotationRadius:rotationRadius
    vertMeasure:vertMeasure
    enterValuesT:enterValues
    unitsBtnT:unitsBtn
    chooseFeedDir:chooseFeedDir
    chooseKinematics:chooseKinematics

    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "This option lets you enter the dimensions of your machine manually which can be faster and easier than the automatic calibration process, but the results might be less accurate"
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Label:
            text: "Distance Between Motors:"
            halign: "center"
        TextInput:
            id: motorsDist
        Label:
            text: "Rotation Radius:"
            halign: "center"
        TextInput:
            id: rotationRadius
        Label:
            text: "Distance from top of workspace to motors:"
            halign: "center"
        TextInput:
            id: vertMeasure
        Button:
            text: "Units: mm"
            on_release: root.switchUnits()
            id: unitsBtn
        Label:
            text: "Kinematics type:"
            halign: "center"
        Spinner:
            id: chooseKinematics
            text: "Triangular"
            values: ["Triangular", "Quadrilateral"]
        Label:
            text: "Chain Feed:"
            halign: "center"
        Spinner:
            id: chooseFeedDir
            text: "Top"
            values: ["Top", "Bottom"]
        Button:
            text: "Enter Values"
            halign: "center"
            on_release: root.enterValues()
            id: enterValues
        Label:

<QuadTestCut>
    cutBtn:cutBtn
    enterValues:enterValues
    horizMeasure:horizMeasure
    vertMeasure:vertMeasure
    unitsBtn:unitsBtn
    enterValues:enterValues
    cols: 2
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "To refine these measurements we're going to cut a test shape.\n\nThe test shape consists of two short horizontal cuts and two short vertical cuts\n\nBased on the distance between these marks we can dial in the machine settings\n\nThe size of bit used is not critical\nMeasure to any point on the mark as long as you are consistent\n\nThe process will repeat until both measurements are equal to within .5mm\nThe more accurate your measurements, the more accurate your machine will be\n\nPress Cut Test Pattern to begin"
            
            text_size: self.size
            valign: 'middle'
        GridLayout:
            cols: 3
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Test Shape Preview.jpg"
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Measure Test Shape Horizontal.jpg"
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Measure Test Shape Vertical.jpg"
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Label:
            text: "Horizontal\nMeasurement:"
        TextInput:
            id:horizMeasure
            disabled: True
        Label:
            text: "Vertical\nMeasurement:"
        TextInput:
            id: vertMeasure
            disabled: True
        Button:
            text: "MM"
            on_release: root.switchUnits()
            id: unitsBtn
            disabled: True
        Button:
            text: "Enter Values"
            on_release: root.enterTestPaternValues()
            id: enterValues
            disabled: True
        Button:
            text: "Cut Test\nPattern"
            id: cutBtn
            on_release: root.cutTestPatern()
        Button:
            text: "Stop\nCut"
            on_release: root.stopCut()
            background_color: (1,.2,.2,1)
        Label:

<MeasureDistBetweenMotors>
    distToMove:distToMove
    distText:distText
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        Label:
            text: "We are going to use the chain to measure the distance between the motors.\n\nHook the first link from the left chain over the top tooth on the left motor as shown in the picture below, then use the 'Extend' button repeatedly to extend the chain until it can reach the right motor. This will take several minutes.\nHint - you can use the distance button to set the length of chain moved for each Extend/Retract action.\n\nOnce the chain has enough slack to reach the right motor, hook the third link on the right motor's 12:00 tooth as shown in the picture below. Use the 'Retract' button to take out sufficient slack to make the chain nearly tight.\nHint - update the distance value to move the chain a short distance to remove most but not all of the slack.\n\nFinally, use the 'Pull Chain Tight and Measure' button to then pull the chain tight and take a measurement.\n\nMake sure the chains do not get tangled around the sprocket. The motors are very powerful and the machine can damage itself this way."
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
        GridLayout:
            cols: 3
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Chain On Left Sprocket.jpg"
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Chain Between Sprockets.jpg"
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Chain On Right Sprocket.jpg"
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Label:
            text: "Dist(MM):"
            id: distText
        Button:
            text: "100"
            on_release: root.textInputPopup(self)
            id: distToMove
        Button:
            text: "Extend"
            on_release: root.extend()
        Button:
            text: "Retract"
            on_release: root.retract()
        Button:
            text: 'Pull Chain Tight\nand Measure'
            on_release: root.pullChainTightAndMeasure()
        Button:
            text: "Stop\nMotors"
            on_release: root.stopCut()
            background_color: (1,.2,.2,1)
        Label:

<MeasureOneChain>
    cols: 2
    width: root.width
    height: root.height
    mainText:mainText
    GridLayout:
        cols: 1
        Label:
            text: " "
            size_hint_x: leftCol
            id: mainText
            text_size: self.size
            valign: 'middle'
        GridLayout:
            cols: 3
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Chain On Left Sprocket.jpg"
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Chain Between Sprockets.jpg"
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Chain On Right Sprocket.jpg"
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: "Extend"
            on_release: root.extend()
        Button:
            text: 'Measure'
            on_release: root.measure()
        Button:
            text: "Stop\nMotors"
            on_release: root.stopCut()
            background_color: (1,.2,.2,1)
        Label:

<VertDistToMotorsGuess>:
    enterMeasurement:enterMeasurement
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "Next we need to enter a rough measurement for how far the motors are above the top of the work area\n\nMeasure from the center of the motor shaft to the top of the sheet of plywood\n\nThis measurement is not critical for the accuracy of the machine, but will move the center position up and down."
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
        GridLayout:
            cols: 2
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Measure Motor Height.jpg"
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: "Enter Measurement"
            id: enterMeasurement
            on_release: root.textInputPopup(self)
        Button:
            text: 'Next'
            on_release: root.enterValues()
        Label:

<AdjustZCalibrationDepth>:
    zAxisActiveSwitch:zAxisActiveSwitch
    openZPopupBtn:openZPopupBtn
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "Next, we are going to define the home position for the z-axis\n\nIf you have an automatic z-axis installed use the buttons to enable it and adjust the z-axis until the router bit\nbarely touches the surface of the wood. Then press Define Zero\n\nIf you do not have the z-axis installed, adjust your router until the router bit just barely\ntouches the surface of the wood, then press Define Zero"
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
        GridLayout:
            cols: 2
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Set Z Height.jpg"
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        GridLayout:
            cols: 2
            Label:
                text: 'Enable\nAutomatic Z-Axis:'
            Switch:
                on_active: root.enableZaxis()
                id: zAxisActiveSwitch
        Button:
            text: "Adjust Z-Axis"
            on_release: root.zAxisPopup()
            disabled:True
            id: openZPopupBtn
        Button:
            text: 'Define Zero'
            on_release: root.zeroZ()
        Label:

<RotationRadiusGuess>:
    enterMeasurement:enterMeasurement
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "Next we need to enter a rough estimate for the rotation radius.\nThis is the distance from the tip of the chain to the center of the router bit.\n\nFor the ring this distance is 140mm\nFor the wooden linkage kits it is around 260mm\nFor the metal linkage kits it is around 150mm\n\n*These numbers are rough and should be updated*"
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: "Enter Measurement"
            id: enterMeasurement
            on_release: root.textInputPopup(self)
        Button:
            text: 'Next'
            on_release: root.enterValues()
        Label:

<DistBetweenChainBrackets>:
    enterMeasurement:enterMeasurement
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "Next we need to enter a rough estimate for the distance between the points where the chains attach to the sled.\n\nThis estimate will be refined by the calibration process in the next step."
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: "Enter Measurement"
            id: enterMeasurement
            on_release: root.textInputPopup(self)
        Button:
            text: 'Next'
            on_release: root.enterValue()
        Label:

<SetSprocketsVertical>:
    #Set sprockets to 12 o'clock
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        Label:
            text: "Orient each sprocket so that one tooth faces straight up in the 12:00 o'clock position.\n\nIt is important to start with the sprockets in a known configuration. \nUse the buttons to the right to rotate each sprocket so that one tooth points straight up.\nWhen you are ready, press Set Zero"
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
        Image:
            source: "./Documentation/Calibrate Machine Dimensions/Sprocket at 12-00.jpg"
    GridLayout:
        cols:1
        size_hint_x: .4
        GridLayout:
            cols: 4
            size_hint_x: .4
            Label:
                text: "Left Sprocket"
                font_size: '20sp'
            Label:
            Label:
            Label:
            Button:
                text: '360 deg CCW'
                on_release: root.LeftCCW360()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '5 deg CCW'
                on_release: root.LeftCCW5()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '1 deg CCW'
                on_release: root.LeftCCW()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '0.1 deg CCW'
                on_release: root.LeftCCWpoint1()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '360 deg CW'
                on_release: root.LeftCW360()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '5 deg CW'
                on_release: root.LeftCW5()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '1 deg CW'
                on_release: root.LeftCW()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '0.1 deg CW'
                on_release: root.LeftCWpoint1()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Label:
                text: "Right Sprocket"
                font_size: '20sp'
            Label:
            Label:
            Label:
            Button:
                text: '360 deg CCW'
                on_release: root.RightCCW360()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '5 deg CCW'
                on_release: root.RightCCW5()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '1 deg CCW'
                on_release: root.RightCCW()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '0.1 deg CCW'
                on_release: root.RightCCWpoint1()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '360 deg CW'
                on_release: root.RightCW360()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '5 deg CW'
                on_release: root.RightCW5()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '1 deg CW'
                on_release: root.RightCW()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Button:
                text: '0.1 deg CW'
                on_release: root.RightCWpoint1()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
            Label:
            Label:
            Label:
            Label:
            Button:
                text: "Automatic"
                on_release: root.setVerticalAutomatic()
                halign: 'center'
                valign: 'middle'
                text_size: self.width, None
                font_size: self.width * 0.15
        GridLayout:
            cols: 1
            size_hint_x: .4
            Label:
            Button:
                text: 'Set Zero'
                on_release: root.setZero()
            Label:

<MeasureOutChains>:
    leftChainBtn:leftChainBtn
    rightChainBtn:rightChainBtn
    leftImg:leftImg
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: root.text
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
        GridLayout:
            cols: 2
            Image:
                id: leftImg
            Image:
                source: "./Documentation/Calibrate Machine Dimensions/Sled Attached.jpg"
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: '   Adjust\nLeft Chain'
            on_release: root.startCountDownL()
            id: leftChainBtn
        Button:
            text: '   Adjust\nRight Chain'
            on_release: root.startCountDownR()
            id: rightChainBtn
        Button:
            text: 'Stop'
            on_release: root.stop()
            background_color: (1,.2,.2,1)
        Button:
            text: 'Move to Center'
            on_release: root.moveToCenter()
        Button:
            text: 'Next'
            on_release: root.next()
        Label:

<Finish>:
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "Congratulations! Your calibration is complete."
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: "Finish"
            on_release: root.closePopup()
        Label:

<FinishSetChainLengths>:
    cols: 2
    width: root.width
    height: root.height
    GridLayout:
        cols: 1
        size_hint_x: leftCol
        Label:
            text: "Congratulations! Your chains have been set to a known length."
            size_hint_x: leftCol
            text_size: self.size
            valign: 'middle'
    GridLayout:
        cols: 1
        size_hint_x: rightCol
        Label:
        Button:
            text: "Finish"
            on_release: root.closePopup()
        Label:

            cols: 2
            Label:
                text: "Your machine is now calibrated!\n\nCongratulations! "
                size_hint_x: leftCol
                id: finishText
            Button:
                text: 'Finish'
                on_release: root.done()
                size_hint_x: rightCol

<CalibrateLengthsPopup>:
    carousel:carousel
    setSprocketsVertical:setSprocketsVertical
    measureOutChains:measureOutChains

    cols: 1
    size: root.size
    pos: root.pos

    Carousel:
        id: carousel
        direction: "right"
        #:set leftCol .8
        #:set rightCol .2
        GridLayout:
            cols: 1
            SetSprocketsVertical:
                id: setSprocketsVertical
        GridLayout:
            cols: 1
            MeasureOutChains:
                id: measureOutChains
        #finish
        GridLayout:
            cols: 2
            width: root.width
            height: root.height
            GridLayout:
                cols: 1
                Label:
                    text: "The machine now has an accurate reading of the lengths of the chains.\n\nPress finish to close the popup"
                    size_hint_x: leftCol
            GridLayout:
                cols: 1
                size_hint_x: rightCol
                Label:
                Button:
                    text: 'Finish'
                    on_release: root.done()
                Label:

#simulation widgets

<SimulationCanvas>:
    motorSpacingError:motorSpacingError
    motorVerticalError:motorVerticalError
    sledMountSpacingError:sledMountSpacingError
    scatterInstance:scatterInstance
    vertBitDist:vertBitDist
    vertCGDist:vertCGDist
    leftChainOffset:leftChainOffset
    rightChainOffset:rightChainOffset
    motorSpacingErrorLabel:motorSpacingErrorLabel
    motorVerticalErrorLabel:motorVerticalErrorLabel
    sledMountSpacingErrorLabel:sledMountSpacingErrorLabel
    vertBitDistLabel:vertBitDistLabel
    vertCGDistLabel:vertCGDistLabel
    leftChainOffsetLabel:leftChainOffsetLabel
    rightChainOffsetLabel:rightChainOffsetLabel
    machineLabel1:machineLabel1
    machineLabel2:machineLabel2
    gridSize:gridSize
    gridSizeLabel:gridSizeLabel
    rotationRadiusOffset:rotationRadiusOffset
    rotationRadiusLabel:rotationRadiusLabel
    chainSagCorrectionOffset:chainSagCorrectionOffset
    chainSagCorrectionLabel:chainSagCorrectionLabel
    kinematicsSelect:kinematicsSelect

    rows: 3
    Label:
        text: "This simulation is designed to help us understand how the math behind Maslow is affected by errors in the computed machine dimensions\nTry adding error to any measurement, then press Recompute to see the affect\nThe path computed with the correct values is shown in green, the path with error added is shown in red"
        size_hint_y:.1
    GridLayout:
        cols: 2
        size_hint_y: .1
        Label:
            text: "Not yet computed"
            id: machineLabel1
            font_size: sp(10)
        Label:
            text: "Not yet computed"
            id: machineLabel2
            font_size: sp(10)
    GridLayout:
        cols: 2
        size_hint_y: .9
        ScatterPlane:
            do_rotation: False
            id: scatterInstance
            size_hint_x: .9

        GridLayout:
            cols: 1
            size_hint_x: .1
            Spinner:
                id: kinematicsSelect
                text: "Kinematics Type"
                values: "Quadrilateral", "Triangular"
                on_text: root.setKinematics(kinematicsSelect.text)
            Label:
                text: "Motor Spacing\nError: 0mm"
                text_size: self.width, self.height
                font_size: sp(self.height)/sp(3)
                id: motorSpacingErrorLabel
            Slider:
                min: -50
                max:50
                value: 0
                id: motorSpacingError
            Label:
                text: "Motor Vertical\nError: 0mm"
                text_size: self.width, self.height
                font_size: sp(self.height)/sp(3)
                id: motorVerticalErrorLabel
            Slider:
                min: -50
                max:50
                value: 0
                id: motorVerticalError
            Label:
                text: "Sled Mount\nSpacing Error: 0mm"
                text_size: self.width, self.height
                font_size: sp(self.height)/sp(3)
                id: sledMountSpacingErrorLabel
                disabled: not root.isQuadKinematics
            Slider:
                min: -50
                max:50
                value: 0
                id: sledMountSpacingError
                disabled: not root.isQuadKinematics
            Label:
                text: "Vert Dist To\nBit Error: 0mm"
                text_size: self.width, self.height
                font_size: sp(self.height)/sp(3)
                id: vertBitDistLabel
                disabled: not root.isQuadKinematics
            Slider:
                min: -50
                max:50
                value: 0
                id: vertBitDist
                disabled: not root.isQuadKinematics
            Label:
                text: "Vert Dist\nBit to CG Error: 0mm"
                text_size: self.width, self.height
                font_size: sp(self.height)/sp(3)
                disabled: not root.isQuadKinematics
                id: vertCGDistLabel
            Slider:
                min: -50
                max:50
                value: 0
                id: vertCGDist
                disabled: not root.isQuadKinematics
            Label:
                text: "Left Chain\nSlipped Links: 0links"
                text_size: self.width, self.height
                font_size: sp(self.height)/sp(3)
                id: leftChainOffsetLabel
            Slider:
                min: -10
                max:10
                value: 0
                id: leftChainOffset
            Label:
                text: "Right Chain\nSlipped Links: 0links"
                text_size: self.width, self.height
                font_size: sp(self.height)/sp(3)
                id: rightChainOffsetLabel
            Slider:
                min: -10
                max:10
                value: 0
                id: rightChainOffset
            Label:
                text: "Rotation Radius"
                text_size: self.width, self.height
                font_size: sp(self.height)/sp(3)
                disabled: root.isQuadKinematics
                id: rotationRadiusLabel
            Slider:
                min: -25
                max:25
                value: 0
                disabled: root.isQuadKinematics
                id: rotationRadiusOffset
            Label:
                text: "Chain Sag Correction"
                text_size: self.width, self.height
                font_size: sp(self.height)/sp(3)
                disabled: root.isQuadKinematics
                id: chainSagCorrectionLabel
            Slider:
                min: -50
                max:50
                value: 0
                disabled: root.isQuadKinematics
                id: chainSagCorrectionOffset
            Label:
                text: "Grid Size: 150mm"
                text_size: self.width, self.height
                font_size: sp(self.height)/sp(3)
                id: gridSizeLabel
            Slider:
                min: 25
                max:300
                value: 300
                id: gridSize

            Button:
                text: "Reset All"
                on_release: root.resetSliders()
            Button:
                text: "Recompute"
                on_release: root.recompute()

<BackgroundMenu>:
    cols:1
    size: root.size
    pos: root.pos
    Button:
        text: 'Open Background'
        on_release: root.openBackground()
	Button:
		text: 'Re-pick Alignment'
		on_release: root.realignBackground()
		disabled: app.data.backgroundTexture is None
    Button:
        text: 'Update Background'
        on_release: root.reloadBackground()
    Button:
        text: 'Remove Background'
        on_release: root.clear_background()
    Button:
        text: 'Close'
        on_press: app.frontpage.gcodecanvas.centerCanvas() #Force canvas redraw
        on_release: root.close()
					
<BackgroundPickDlg>
    imWidg:imWidg
    cols: 1
    size: root.size
	pos: root.pos
	GridLayout:
		cols: 4
        Button:
            size_hint_x: None
			size_hint: 0.5, 1
            text: 'Reset Image'
            on_release: root.reset_image()
        Label:
            size_hint_x: None
			size_hint: 2.5, 1
			text_size: self.width, self.height
			font_size: sp(self.height)/sp(5)
            halign: 'center'
			valign: 'middle'
            text: root.instructionText
        Button:
            size_hint_x: None
			size_hint: 0.5, 1
            text: 'Resize Texture'
            on_release: root.resize_texture()
        Button:
            size_hint_x: None
			size_hint: 0.5, 1
            text: 'Accept'
            on_press: app.frontpage.gcodecanvas.centerCanvas() #Force canvas redraw
            on_release: root.accept_texture()
    Widget:
        size_hint_y: None
        size_hint: 1, 7
        id: imWidg
        canvas:
            Color:
                rgba: 1, 1, 1, 1
            Rectangle:
                texture: root.texture
                pos: self.pos
    			size: self.size
                tex_coords: root.tex_coords
            Color:
                rgba: 1, 0, 0, 0.5
            Line:
                points: root.tex_selection
                close: True
            Color:
                rgba: 0, 1, 1, 0.3
            Line:
                circle: root.tex_selection[0], root.tex_selection[1], 10
            Line:
                circle: root.tex_selection[2], root.tex_selection[3], 10
            Line:
                circle: root.tex_selection[4], root.tex_selection[5], 10
            Line:
                circle: root.tex_selection[6], root.tex_selection[7], 10

<TestPoint>

#:import pi math.pi
#:import cos math.cos
#:import sin math.sin
#:import V kivy.vector.Vector
<ModernMenu>:
    canvas.before:
        Color:
            rgba: 1, 1, 1, 1
        Ellipse:
            pos: self.center_x - self.radius, self.center_y - self.radius
            size: self.radius * 2, self.radius * 2
            angle_start: 0
            angle_end: self.circle_progress * 360 * self.creation_direction
        Color:
            rgba: self.color
        Line:
            circle:
                (
                self.center_x, self.center_y,
                self.radius, 0, self.circle_progress * 360 * self.creation_direction
                )
            width: self.line_width
    on_touch_down:
        V(args[1].pos).distance(self.center) < self.radius and (
        self.back() if self.choices_history else self.dismiss())

<ModernMenuLabel>:
    size: self.texture_size
    padding: 5, 5
    on_press: self.callback and self.callback(self)
    on_release: root.dismiss()
    canvas.before:
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            pos: self.pos
            size: self.size
        Line:
            points:
                (
                self.center_x, self.center_y,
                self.parent.center_x + cos(
                self.opacity * self.index * 2 * pi / self.siblings
                ) * self.parent.radius,
                self.parent.center_y + sin(
                self.opacity * self.index * 2 * pi / self.siblings
                ) * self.parent.radius
                ) if self.parent else []
            width: self.parent.line_width if self.parent else 1
    center:
        (
        self.parent.center_x +
        cos(self.opacity * self.index * 2 * pi / self.siblings) * self.radius,
        self.parent.center_y +
        sin(self.opacity * self.index * 2 * pi / self.siblings) * self.radius
        ) if (self.size and self.parent and self.parent.children) else (0, 0)
